using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using System.ComponentModel;
using System.Web.UI.Design;

using PHSRAG.Insight21.ClinicalTrials;

namespace PHSRAG.Insight21.InsightWebControls.ClinicalTrials
{
	/// <summary>
   /// The Budget Expenses Control is used as a container for all BudgetExpense controls.  
   /// It also contains buttons for action on the contained controls
   /// </summary>
   [ToolboxData("<{0}:BudgetExpensesControl runat=server></{0}:BudgetExpensesControl>"),Designer(typeof(BudgetExpensesControlDesigner))]
   public class BudgetExpensesControl : System.Web.UI.Control, INamingContainer
   {
      #region Instance Variables
      private Budget budget;
      private ArrayList budgetExpenseControls = new ArrayList( );
      private ArrayList budgetVarCostControls = new ArrayList( );
      private Button addMoreCosts;
      private Button addMoreVariableCosts;
      private Button deleteCosts;
      private Button deleteVariableCosts;
      private Button saveExpenses;
      private ValidationSummary validationSummary;
      #endregion

      #region Constants
      /// <summary>
      /// Number of controls between the Add More Costs button and the last Cost control, used to determine
      /// where in the control tree to add new cost controls
      /// </summary>
      private const int addCostsControlIndex = 1;
      /// <summary>
      /// Number of controls between the Add More Variable Costs button and the last Variable Cost control, 
      /// used to determine where in the control tree to add new variable cost controls
      /// </summary>
      private const int addVarCostsControlIndex = 1;
      #endregion

       #region public properties
       public string SaveButtonClientId
       {
           get { EnsureChildControls(); return saveExpenses.ClientID; }
       }

       public string DeleteCostsButtonClientId
       {
           get { EnsureChildControls(); return deleteCosts.ClientID; }
       }

       public string DeleteVariableCostsButtonClientId
       {
           get { EnsureChildControls(); return deleteVariableCosts.ClientID; }
       }
       #endregion
       
        #region Overrides
      /// <summary>
      /// Runs upon loading of the control
      /// </summary>
      /// <param name="e"></param>
      protected override void OnLoad(EventArgs e)
      {
         base.OnLoad(e);
         EnsureChildControls( );
      }

      /// <summary>
      /// Called by EnsureChildControls to add all child controls to the control tree.
      /// </summary>
      protected override void CreateChildControls( )
      {
         budget = (Budget)((Policy.ICachePolicy)Page.Session[Policy.Names.CachePolicyKey]).GetCachedObject( Budget.CacheKey );
         CreateControls( );
         GenerateControlTree( );
      }
      #endregion

      #region Private Methods
      /// <summary>
      /// Creates the actual controls, applying styles, setting values and binding validation.
      /// </summary>
      private void CreateControls( )
      {
         validationSummary = new ValidationSummary( );
         validationSummary.HeaderText = "The following errors have occurred.";
         validationSummary.ShowSummary = true;

         BudgetExpenses budgetExpenses = budget.BudgetExpenses;
         int numberOfExpenses = budgetExpenses.Count;
         // For each budget Expense object, create a control and add it to the arraylist
         for ( int i = 0; i < numberOfExpenses; ++i )
         {
            BudgetExpenseControl newControl = new BudgetExpenseControl( budgetExpenses[i] );
            newControl.ID = string.Format( "budgetExpense{0}", i );
            budgetExpenseControls.Add( newControl );
         }

         BudgetExpenses budgetVarCosts = budget.BudgetVariableCosts;
         // For each Budget Variable Cost object, create a budget var cost control and add it to the arraylist
         int numberOfVarCosts = budgetVarCosts.Count;
         for ( int i = 0; i < numberOfVarCosts; ++i )
         {
            BudgetVarCostControl newControl = new BudgetVarCostControl( budgetVarCosts[i] );
            newControl.ID = string.Format( "budgetVarCost{0}", i );
            budgetVarCostControls.Add( newControl );
         }

         // Setup buttons
         addMoreCosts = new Button( );
         addMoreCosts.ID = "addMoreCosts";
         addMoreCosts.CssClass = "Button";
         addMoreCosts.Text = "Add More Costs";
         addMoreCosts.Click += new EventHandler(OnAddMoreCosts);
         addMoreVariableCosts = new Button( );
         addMoreVariableCosts.ID = "addMoreVariableCosts";
         addMoreVariableCosts.CssClass = "Button";
         addMoreVariableCosts.Text = "Add More Variable Costs";
         addMoreVariableCosts.Click += new EventHandler(OnAddMoreVariableCosts);
         deleteCosts = new Button( );
         deleteCosts.ID = "deleteCosts";
         deleteCosts.CssClass = "Button";
         deleteCosts.Text = "Delete Costs";
         deleteCosts.Click += new EventHandler(OnDeleteCosts);
         deleteVariableCosts = new Button( );
         deleteVariableCosts.ID = "deleteVariableCosts";
         deleteVariableCosts.CssClass = "Button";
         deleteVariableCosts.Text = "Delete Variable Costs";
         deleteVariableCosts.Click += new EventHandler(OnDeleteVariableCosts);
         saveExpenses = new Button( );
         saveExpenses.ID = "saveExpenses";
         saveExpenses.CssClass = "Button";
         saveExpenses.Text = "Save";
         saveExpenses.Click += new EventHandler(OnSaveExpenses);
      }

      /// <summary>
      /// Adds the controls to the control tree
      /// </summary>
      private void GenerateControlTree( )
      {
         Controls.Add( validationSummary );

         Controls.Add( new LiteralControl(
             "<table width=\"60%\" style=\"height: 5px; background-color:#5a76a0; color:White; font-weight:bold\">\n" +
             "<tr><td>Budget Costs</td></tr></table>" +
             "<table width=\"60%\" class=\"DataGrid\">\n" +
            "\t<tr class=\"DataGridHeader\">" +
            "\t\t<td width=\"75%\">Expense Description <br/>" +
            "(uncheck if overhead should not be applied)" +
            "\t\t</td>\n" +
            "\t\t<td width=\"15%\">Cost</td>\n" +
            "\t\t<td width=\"10%\">Delete</td>\n" +
            "\t</tr>" ) );

         foreach( BudgetExpenseControl budgetExpenseControl in budgetExpenseControls )
         {
            Controls.Add( budgetExpenseControl );
         }

         Controls.Add(new LiteralControl(
            "<tr><td colspan=\"3\">" ));
         
         Controls.Add( addMoreCosts );
         Controls.Add( new LiteralControl( "&nbsp;" ) );
         Controls.Add( deleteCosts );

         Controls.Add(new LiteralControl(
            "\t\t</td>\n" + 
            "\t</tr>\n" + 
            "</table>" ) );

         Controls.Add( new LiteralControl(
            "<protocolId/>" +
            "<table width=\"60%\" style=\"height: 5px; background-color:#5a76a0; color:White; font-weight:bold\">\n" +
            "<tr><td>Budget Variable Costs</td></tr></table>" +
            "<table width=\"60%\" class=\"DataGrid\">\n" +
            "\t<tr class=\"DataGridHeader\">" +
            "\t\t<td width=\"75%\"> Variable Cost Agreements</td>\n" +
            "\t\t<td width=\"15%\">Cost</td>\n" +
            "\t\t<td width=\"10%\">Delete</td>\n" +
            "\t</tr>" ) );

         foreach( BudgetVarCostControl budgetVarCostControl in budgetVarCostControls )
         {
            Controls.Add( budgetVarCostControl );
         }

         Controls.Add(new LiteralControl(
            "<tr><td colspan=\"3\">" ));
         
         Controls.Add( addMoreVariableCosts );
         Controls.Add( new LiteralControl( "&nbsp;" ) );
         Controls.Add( deleteVariableCosts );

         Controls.Add(new LiteralControl(
            "</td></tr>\n" +
            "\t</tr>\n" +
            "</table>" +
            "<table width=\"60%\">\n" +
            "\t<tr><td></td></tr>\n" +
            "\t<tr><td></td></tr>\n" +
            "\t<tr><td></td></tr>\n" +
            "\t<tr>\n" + 
            "\t\t<td>\n" ) );

         Controls.Add( saveExpenses );

         Controls.Add( new LiteralControl(
            "</td></tr>\n" +
            "\t</tr>\n" +
            "</table>" ) );
      }
      #endregion

      #region Event Handlers
      /// <summary>
      /// Event handler for adding a new cost
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void OnAddMoreCosts(object sender, EventArgs e)
      {
         BudgetExpenses budgetExpenses = budget.BudgetExpenses;
         BudgetExpense newBudgetExpense = budgetExpenses.CreateNewBudgetExpense( false );
         BudgetExpenseControl newControl = new BudgetExpenseControl( newBudgetExpense );
         newControl.ID = string.Format( "budgetExpense{0}", ((budgetExpenses.Count - 1) as object) );
         Control addMoreCostsButton = FindControl( "addMoreCosts" );
         Controls.AddAt( Controls.IndexOf( addMoreCostsButton ) - addCostsControlIndex, newControl );
      }

      /// <summary>
      /// Event handler for deleting costs
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void OnDeleteCosts(object sender, EventArgs e)
      {
         BudgetExpenses budgetExpenses = budget.BudgetExpenses;
         // Recurse through the list from the last item to the first, this keeps the counts 
         // synchronized, so we don't skip any or try to get controls or objects which don't 
         // exist anymore
         int lastItemIndex = budgetExpenses.Count - 1;
         for( int i = lastItemIndex; i >= 0; --i )
         {
            BudgetExpenseControl budgetExpenseControl = (BudgetExpenseControl)budgetExpenseControls[i];
            if ( budgetExpenseControl.Delete )
            {
               BudgetExpense budgetExpense = budgetExpenses[i];
               budgetExpenses.RemoveBudgetExpense( budgetExpense );
            }
         }
         budgetExpenses.Save( Utility.DataAccess.GetConnectionString( ) );
         // Reload the page since controls which we wanted to remove have already been created
         Page.Server.Transfer( "BudgetOtherCosts.aspx" );
      }

      /// <summary>
      /// Event handler for adding a variable cost
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void OnAddMoreVariableCosts(object sender, EventArgs e)
      {
         BudgetExpenses budgetExpenses = budget.BudgetVariableCosts;
         BudgetExpense newBudgetVarCost = budgetExpenses.CreateNewBudgetExpense( true );
         BudgetVarCostControl newControl = new BudgetVarCostControl( newBudgetVarCost );
         newControl.ID = string.Format( "budgetVarCost{0}", ((budgetExpenses.Count - 1) as object) );
         Controls.AddAt( Controls.IndexOf( addMoreVariableCosts ) - addVarCostsControlIndex, newControl );
      }

      /// <summary>
      /// Event handler for deleting variable costs
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void OnDeleteVariableCosts(object sender, EventArgs e)
      {
          BudgetExpenses budgetVarCosts = budget.BudgetVariableCosts;
          // Recurse through the list from the last item to the first, this keeps the counts 
          // synchronized, so we don't skip any or try to get controls or objects which don't 
          // exist anymore
          int lastItemIndex = budgetVarCosts.Count - 1;
          for( int i = lastItemIndex; i >=0; --i )
          {
              BudgetVarCostControl budgetVarCostControl = (BudgetVarCostControl)budgetVarCostControls[i];
              if ( budgetVarCostControl.Delete )
              {
                  BudgetExpense budgetVarCost = budgetVarCosts[i];
                  budgetVarCosts.RemoveBudgetExpense( budgetVarCost );
              }
          }
          budgetVarCosts.Save( Utility.DataAccess.GetConnectionString( ) );
          Page.Server.Transfer( "BudgetOtherCosts.aspx" );
      }

      /// <summary>
      /// Event handler for saving budget expenses
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void OnSaveExpenses(object sender, EventArgs e)
      {
         BudgetExpenses budgetExpenses = budget.BudgetExpenses;
         for(int i = 0; i < budgetExpenses.Count; ++i)
         {
            BudgetExpense budgetExpense = budgetExpenses[i];
            BudgetExpenseControl budgetExpenseControl = (BudgetExpenseControl)budgetExpenseControls[i];
            budgetExpense.ApplyOverhead = budgetExpenseControl.ApplyOverhead;
            if ( budgetExpense.StudyCostCode == "ClinicalTrialBudgetExpenseOther" )
            {
               budgetExpense.OtherExpenseText = budgetExpenseControl.OtherExpense;
            }
            budgetExpense.ExpenseCost = budgetExpenseControl.ExpenseCost;
         }
         budget.BudgetExpenses.Save( Utility.DataAccess.GetConnectionString( ) );

         BudgetExpenses budgetVarCosts = budget.BudgetVariableCosts;
         for(int i = 0; i < budgetVarCosts.Count; ++i)
         {
            BudgetExpense budgetVarCost = budgetVarCosts[i];
            BudgetVarCostControl budgetVarCostControl = (BudgetVarCostControl)budgetVarCostControls[i];
            budgetVarCost.ApplyOverhead = budgetVarCostControl.ApplyOverhead;
            budgetVarCost.StudyCostCode = budgetVarCostControl.CostDescription;
            budgetVarCost.ExpenseCost = budgetVarCostControl.CostAmount;
            budgetVarCost.VariableCost = true;
         }
         budget.BudgetVariableCosts.Save( Utility.DataAccess.GetConnectionString( ) );
      }
      #endregion
   }

   #region Class BudgetExpensesControlDesigner
   /// <summary>
   /// Designer associated with the BudgetExpensesControl.
   /// </summary>
   /// <remarks>
   /// This class cannot be used directly.
   /// </remarks>
   public class BudgetExpensesControlDesigner : ControlDesigner
   {
      #region Overrides
      /// <summary>
      /// Since the BudgetExpensesControl does not have any design-time visibility, the designer provides
      /// the type name of that control and the name of the instance.
      /// </summary>
      /// <returns>HTML representation of the BudgetExpensesControl</returns>
      public override string GetDesignTimeHtml( )
      {
         return CreatePlaceHolderDesignTimeHtml( );
      }
      #endregion
   }
   #endregion
}
